package org.gwt.pluginframework.plugin.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class Wizard implements IWizard {

	protected List<Container> sequence = new ArrayList<Container>(); 
	
	protected Map<String, Container> register = new HashMap<String, Container>();

	protected Container current;

	protected Window window;
	
	protected ContentPanel panel;
	
	protected Label message;
	
	protected Button previous;
	
	protected Button next;
	
	protected Button finish;
	
	protected Button cancel;
	
	protected String title;
	
	public Wizard() {
		this.title = "Wizard";
	}
	
	public Wizard(String title) {
		this.title = title;
	}
	
	public void create() {
		window = new Window();
		window.setSize(600, 400);
		window.setHeading(title);
		window.setScrollMode(Scroll.AUTOY);
		window.setLayout(new FitLayout());
		window.setTopComponent(createTopComponent());
		window.add(createCenterComponent());
		window.addListener(Events.Hide, new Listener<WindowEvent>() {
			public void handleEvent(WindowEvent we) {
				cancel();
			}
		});
		createBottomComponent();
	}
	
	public void start() {
		window.show();
		
		// fixing bug in render
		window.setSize(600, 400);
	}
	
	protected void showPage(IPage page) {
		panel.removeAll();
		panel.add(page.getWiget());
		panel.layout();
	}
	
	public Widget createCenterComponent() {
		panel = new ContentPanel();
		panel.setFrame(true);
		panel.setHeaderVisible(false);
		showPage(current.page);
		return panel;
	}
	
	public void createBottomComponent() {
		previous = new Button("Previous", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				previous();
			}
		});
		previous.disable();
		window.addButton(previous);
		
		next = new Button("Next", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				next();
			}
		});
		if(sequence.size() < 2) {
			next.disable();
		}
		window.addButton(next);
		
		finish = new Button("Finish", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				finish();
			}
		});
		window.addButton(finish);
		
		cancel = new Button("Cancel");
		cancel.addSelectionListener(new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				cancel();
			}
		});
		window.addButton(cancel);
	}
	
	public Component createTopComponent() {
		ContentPanel panel = new ContentPanel();
		panel.setHeaderVisible(false);
		panel.setLayout(new RowLayout());
		panel.setBodyStyle("backround-color: gray;");
		
		panel.add(new Label(current.title));
		panel.add(new Label(current.description));

		message = new Label(" ");
		panel.add(message); 
		
		return panel;
	}
	
	protected void destroy() {
		register.clear();
		current = null;
		panel = null;
		window.hide();
		window = null;
	}
	
	public void next() {
		if(current.page.validate()) {
			int index = sequence.indexOf(current);
			if(index < sequence.size() - 1) { 
				index++;
				current = sequence.get(index);
				panel.add(current.page.getWiget());
				showPage(current.page);
				previous.enable();
			} 
			if(index + 1 >= sequence.size() - 1) {
				next.disable();
			}
		} else {
			message.setText("Form contains errors!");
		}
	}

	public void previous() {
		int index = sequence.indexOf(current);
		if(index > 0) {
			current = sequence.get(index - 1);
			showPage(current.page);
			index--;
			if(index < 1) {
				previous.disable();
			}
			if(index < sequence.size() - 1) {
				next.enable();
			} else {
				next.disable();
			}
		} else {
			previous.disable();
		}
	}

	public void cancel() {
		destroy();
	}

	public void finish() {
		if(current.page.validate()) {
			
			destroy();
		} else { 
			message.setText("Form contains errors!");
		}
	}

	public IPage getCurrentPage() {
		if(current != null) {
			return current.page;
		} 
		throw new IllegalStateException("No current page!");
	}
	
	public void registerPage(String pageId, IPage page, String title,
			String description) {
		if (null == pageId || "".equals(pageId)) {
			throw new IllegalArgumentException("Page id can not be null or empty!");
		}
		if (register.containsKey(pageId)) {
			throw new IllegalArgumentException("Page under id '" + pageId + "' already registered!");
		}
		if (null == page) {
			throw new IllegalArgumentException("Page can not be null!");
		}
		
		Container container = new Container(page, title, description);
		register.put(pageId, container);
		sequence.add(container);
		
		if(current == null) {
			current = container;
		}
	}

	protected class Container {
		public IPage page;
		public String title;
		public String description;
		
		public Container(IPage page, String title, String description) {
			this.page = page;
			this.title = title;
			this.description = description;
		}
	}
}

